package net.keebook.webapp.bean;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import net.keebook.webapp.dao.GroupDao;
import net.keebook.webapp.dao.KeeBookDao;
import net.keebook.webapp.dao.PasswordDao;
import net.keebook.webapp.dao.SettingDao;
import net.keebook.webapp.entity.ItemGroup;
import net.keebook.webapp.entity.KeeBook;
import net.keebook.webapp.entity.PasswordItem;
import net.keebook.webapp.model.SessionModel;
import net.keebook.webapp.util.AccessRight;
import net.keebook.webapp.util.DateUtil;
import net.keebook.webapp.util.MessageBundle;
import net.keebook.webapp.util.SettingId;

import org.apache.log4j.Logger;


@ManagedBean
@RequestScoped
public class AddEntryBean {
	private String itemId;
	private String title;
	private String username;
	private String password;
	private String url;
	private String notes;
	private Date creationTime;
	private Date lastModification;
	private String group;
	private String groupName;
	@Inject
	private PasswordDao passwordDao;
	@Inject
	private GroupDao groupDao;
	@Inject
	private SettingDao settingDao;
	@Inject
	private KeeBookDao keeBookDao;
	private SessionModel sessionModel;
	
	@PostConstruct
	public void init() throws IOException {
		setSessionModel(SessionModel.getInstance(FacesContext.getCurrentInstance()));
		
		if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_ONLY)) {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
		
		if (FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().containsKey("id")) {
			String id = new String(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id"));
			PasswordItem item = getPasswordDao().get(id);
			if (item == null || !getPasswordDao().canAccess(getSessionModel().getUserId(), item.getId())) {
				Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
				FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
				return;
			}
			setItemId(item.getExposableId());
			setTitle(item.getTitle());
			setUsername(item.getUsername());
			setPassword(item.getPassword());
			setUrl(item.getUrl());
			setNotes(item.getNotes());
			setCreationTime(item.getCreationTime());
			setLastModification(item.getLastModification());
			setGroup(item.getGroup() == null ? null : item.getGroup().getExposableId());
		}
	}
	
	public List<ItemGroup> getGroups() {
		return getGroupDao().getList(getSessionModel().getUserId(), getSessionModel().getKeeBookId());
	}
	
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getNotes() {
		return notes;
	}
	public void setNotes(String notes) {
		this.notes = notes;
	}
	public String getItemId() {
		return itemId;
	}
	public void setItemId(String itemId) {
		this.itemId = itemId;
	}
	
	private void setItemProperties(PasswordItem item) {
		KeeBook keeBook = getKeeBookDao().get(getSessionModel().getKeeBookId());
		
		item.setTitle(getTitle());
		item.setUsername(getUsername());
		item.setPassword(getPassword());
		item.setUrl(getUrl());
		item.setNotes(getNotes());
		item.setKeeBook(keeBook);
		item.setLastModification(DateUtil.getUtcTimestamp(TimeZone.getTimeZone(getSettingDao().get(SettingId.SYSTEM_TIMEZONE).getValue())));
		
		if (getGroup() != null && !getGroup().isEmpty()) {
			ItemGroup group;
			if (getGroup().equals("c")) {
				group = new ItemGroup();
				group.setTitle(getGroupName());
				group.setKeeBook(keeBook);
				getGroupDao().store(group);
			} else {
				group = getGroupDao().get(getGroup());
			}
			item.setGroup(group);
		} else {
			item.setGroup(null);
		}
	}
	
	public void save() throws IOException {
		if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_WRITE)) {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
		
		PasswordItem item = new PasswordItem();
		item.setCreationTime(DateUtil.getUtcTimestamp(TimeZone.getTimeZone(getSettingDao().get(SettingId.SYSTEM_TIMEZONE).getValue())));
		setItemProperties(item);
		getPasswordDao().store(item);
		FacesContext.getCurrentInstance().getExternalContext().redirect("index.xhtml?highlight="+item.getExposableId());
	}

	public void update() throws IOException {
		if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_WRITE)) {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
		
		PasswordItem item = getPasswordDao().get(getItemId());
		if (item == null || !getPasswordDao().canAccess(getSessionModel().getUserId(), item.getId())) {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
		setItemProperties(item);
		getPasswordDao().update(item);
		FacesContext.getCurrentInstance().getExternalContext().redirect("index.xhtml?highlight="+item.getExposableId());
	}
	
	public void validateGroupName(FacesContext context, UIComponent component, Object value) {
		UIInput groupSelect = (UIInput)context.getViewRoot().findComponent("addEntryForm:group");
		String group = (String)groupSelect.getValue();
		String groupName = (String)value;
		if ("c".equals(group) && groupName.trim().isEmpty()) {
			((UIInput)component).setValid(false);
			context.addMessage(component.getClientId(context), new FacesMessage(MessageBundle.get().getString("generic.valueRequired")));
		}
	}

	public Date getCreationTime() {
		return creationTime;
	}

	public void setCreationTime(Date creationTime) {
		this.creationTime = creationTime;
	}

	public Date getLastModification() {
		return lastModification;
	}

	public void setLastModification(Date lastModification) {
		this.lastModification = lastModification;
	}

	public GroupDao getGroupDao() {
		return groupDao;
	}

	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}

	public String getGroup() {
		return group;
	}

	public void setGroup(String group) {
		this.group = group;
	}
	
	public SettingDao getSettingDao() {
		return settingDao;
	}

	public void setSettingDao(SettingDao settingDao) {
		this.settingDao = settingDao;
	}

	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public SessionModel getSessionModel() {
		return sessionModel;
	}

	public void setSessionModel(SessionModel sessionModel) {
		this.sessionModel = sessionModel;
	}

	public KeeBookDao getKeeBookDao() {
		return keeBookDao;
	}

	public void setKeeBookDao(KeeBookDao keeBookDao) {
		this.keeBookDao = keeBookDao;
	}

	public PasswordDao getPasswordDao() {
		return passwordDao;
	}

	public void setPasswordDao(PasswordDao passwordDao) {
		this.passwordDao = passwordDao;
	}
}
